using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

using SLProxy;
using libsecondlife;
using libsecondlife.Packets;
using System.Net;
using System.Reflection;

namespace StickyChat
{
    public class StickyAnalyst : UserControl, StickIn
    {
        private StickyServices loader;
        private string myName;
        private CheckedListBox packetTypesBoxes;
        private TextBox AnalystOutput;
        private Button checkAllButton;
        private Button uncheckAllButton;
        private TextBoxWriter output;
        private SortedList<string, PacketType> packetTypes;

        public StickyAnalyst(StickyServices p)
        {
            loader = p;
            InitializeComponent();
            myName = "Analyst";
            Assembly libsl = Assembly.GetAssembly(typeof(PacketType));
            packetTypes = new SortedList<string, PacketType>();
            foreach (FieldInfo packetType in typeof(PacketType).GetFields())
            {
                if (libsl.GetType("libsecondlife.Packets."+packetType.Name + "Packet", false) != null)
                {
                    Type type = typeof(PacketType);
                    FieldInfo field=type.GetField(packetType.Name);
                    packetTypes.Add(packetType.Name, (PacketType)Enum.ToObject(type, (int)field.GetValue(type)));
                }
            }
            packetTypesBoxes.Items.AddRange(new List<string>(packetTypes.Keys).ToArray());

            output = new TextBoxWriter(AnalystOutput);
        }

        #region StickIn Members

        public string name
        {
            get { return myName; }
        }

        public void start() {}
        public void stop() {}
        #endregion StickIn Members

        private void InitializeComponent()
        {
            this.packetTypesBoxes = new System.Windows.Forms.CheckedListBox();
            this.AnalystOutput = new System.Windows.Forms.TextBox();
            this.checkAllButton = new System.Windows.Forms.Button();
            this.uncheckAllButton = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // packetTypesBoxes
            // 
            this.packetTypesBoxes.CheckOnClick = true;
            this.packetTypesBoxes.FormattingEnabled = true;
            this.packetTypesBoxes.Location = new System.Drawing.Point(3, 32);
            this.packetTypesBoxes.Name = "packetTypesBoxes";
            this.packetTypesBoxes.Size = new System.Drawing.Size(169, 319);
            this.packetTypesBoxes.TabIndex = 0;
            this.packetTypesBoxes.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.packetTypesBoxes_ItemCheck);
            // 
            // AnalystOutput
            // 
            this.AnalystOutput.Location = new System.Drawing.Point(178, 3);
            this.AnalystOutput.Multiline = true;
            this.AnalystOutput.Name = "AnalystOutput";
            this.AnalystOutput.ScrollBars = System.Windows.Forms.ScrollBars.Both;
            this.AnalystOutput.Size = new System.Drawing.Size(546, 349);
            this.AnalystOutput.TabIndex = 1;
            // 
            // checkAllButton
            // 
            this.checkAllButton.Enabled = false;
            this.checkAllButton.Location = new System.Drawing.Point(3, 3);
            this.checkAllButton.Name = "checkAllButton";
            this.checkAllButton.Size = new System.Drawing.Size(88, 23);
            this.checkAllButton.TabIndex = 2;
            this.checkAllButton.Text = "Check All";
            this.checkAllButton.UseVisualStyleBackColor = true;
            this.checkAllButton.Click += new System.EventHandler(this.checkAllButton_Click);
            // 
            // uncheckAllButton
            // 
            this.uncheckAllButton.Enabled = false;
            this.uncheckAllButton.Location = new System.Drawing.Point(97, 3);
            this.uncheckAllButton.Name = "uncheckAllButton";
            this.uncheckAllButton.Size = new System.Drawing.Size(75, 23);
            this.uncheckAllButton.TabIndex = 3;
            this.uncheckAllButton.Text = "Uncheck All";
            this.uncheckAllButton.UseVisualStyleBackColor = true;
            this.uncheckAllButton.Click += new System.EventHandler(this.uncheckAllButton_Click);
            // 
            // StickyAnalyst
            // 
            this.Controls.Add(this.uncheckAllButton);
            this.Controls.Add(this.checkAllButton);
            this.Controls.Add(this.AnalystOutput);
            this.Controls.Add(this.packetTypesBoxes);
            this.Name = "StickyAnalyst";
            this.Size = new System.Drawing.Size(724, 360);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        private void packetTypesBoxes_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            try
            {
                if (loader.proxy != null)
                {
                    if (e.NewValue == CheckState.Checked)
                    {
                        loader.proxy.AddDelegate(packetTypes[packetTypesBoxes.Items[e.Index].ToString()], Direction.Incoming, LogPacketIn);
                        loader.proxy.AddDelegate(packetTypes[packetTypesBoxes.Items[e.Index].ToString()], Direction.Outgoing, LogPacketOut);
                    }
                    else
                    {
                        loader.proxy.RemoveDelegate(packetTypes[packetTypesBoxes.Items[e.Index].ToString()], Direction.Incoming, LogPacketIn);
                        loader.proxy.RemoveDelegate(packetTypes[packetTypesBoxes.Items[e.Index].ToString()], Direction.Outgoing, LogPacketOut);
                        e.NewValue = CheckState.Unchecked;
                    }
                }
                else
                {
                    e.NewValue = CheckState.Unchecked;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
        }

        private Packet LogPacketIn(Packet packet, IPEndPoint sim)
        {
            LogPacket(packet, sim, Direction.Incoming);
            return packet;
        }

        private Packet LogPacketOut(Packet packet, IPEndPoint sim)
        {
            LogPacket(packet, sim, Direction.Outgoing);
            return packet;
        }

        private Packet LogPacket(Packet packet, IPEndPoint sim, Direction direction)
        {
            StringBuilder msg = new StringBuilder();
            msg.AppendLine();
            msg.Append((direction == Direction.Incoming) ? "<--" : "-->");
            if (packet.Header.Flags != 0)
            {
                msg.Append("(");
                msg.Append(((packet.Header.Flags & Helpers.MSG_APPENDED_ACKS) != 0) ? "Acks" : "");
                msg.Append(((packet.Header.Flags & Helpers.MSG_RELIABLE) != 0) ? "Reliable" : "");
                msg.Append(((packet.Header.Flags & Helpers.MSG_RESENT) != 0) ? "Resent" : "");
                msg.Append(((packet.Header.Flags & Helpers.MSG_ZEROCODED) != 0) ? "Zerocoded" : "");
                msg.Append(")");
            }
            msg.AppendLine();
            msg.Append(packet.ToString());
            output.WriteLine(msg.ToString());
            return packet;
        }

        private void checkAllButton_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < packetTypesBoxes.Items.Count; i++)
            {
                packetTypesBoxes.SetItemChecked(i, true);
            }
        }

        private void uncheckAllButton_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < packetTypesBoxes.Items.Count; i++)
            {
                packetTypesBoxes.SetItemChecked(i, false);
            }
        }
    }
}